﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web.Compilation;
using Kratos.Framework.Configurations;
using Kratos.Framework.Extensions;
using Microsoft.Practices.Unity;

namespace Kratos.Framework.Infrastructures
{
    public class ModulesLoaded : IModulesLoaded
    {
        private readonly IUnityContainer _container;
        private readonly IList<IKratosModule> _modules;

        public ModulesLoaded(IUnityContainer container)
        {
            _container = container;
            _modules = new List<IKratosModule>(10);
        }

        public IKratosModule Load(KratosConfigurationSection kratosSection, KratosModuleConfigurationElement module)
        {
            if (module == null) return null;
            Type moduleType = Type.GetType(module.Type);

            if (moduleType == null)
                foreach (var ass in BuildManager.CodeAssemblies)//从App_code目录中的程序集中去找类型
                {
                    moduleType = ((Assembly)ass).GetExportedTypes().FirstOrDefault(t => t.FullName == module.Type);
                    if (moduleType != null) break;
                }

            if (moduleType == null)
                throw new TypeLoadException("找不到类型 '{0}'.".With(module.Type));

            //获取provider的实例,并做一些配置
            foreach (KratosDataProviderConfigurationElement provider in kratosSection.DataProviders)
            {
                //加载与模块对应的provider
                if (provider.Name == module.Name)
                {
                    Type providerType = Type.GetType(provider.Type);
                    if (providerType == null)
                        throw new TypeLoadException(string.Format("找不到类型 '{0}'.", provider.Type));
                    var providerInstance = _container.Resolve(providerType) as IKratosDataProvider;
                    if (providerInstance != null)
                    {
                        //配置DataProvider
                        providerInstance.ConfigDataProvider();
                    }
                    break;
                }
            }

            var moduleInstance = _container.Resolve(moduleType) as IKratosModule;

            if (moduleInstance == null)
                throw new Exception("获取类型 '{0}' 的实例失败.".With(module.Type));

            _modules.Add(moduleInstance);

            return moduleInstance;
        }

        public IEnumerable<IKratosModule> GetModules()
        {
            return GetModules<IKratosModule>();
        }

        public IEnumerable<T> GetModules<T>() where T : IKratosModule
        {
            return _modules.Where(t => t is T).Cast<T>();
        }

        public void UnloadModules()
        {
            foreach (IKratosModule module in _modules)
                module.Unload();

            _modules.Clear();
        }
    }
}
